﻿using GameFramework.DataTable;
using GameHelper;
using System;
using System.Collections.Generic;
using TowerDefence_Zombie.Data;
using UnityEngine;
using Random = UnityEngine.Random;

namespace TowerDefence_Zombie
{
    public sealed class MoneyEntityData
    {
        private DRMoneyEntity dRMoneyEntity;

        public int Id
        {
            get
            {
                return dRMoneyEntity.Id;
            }
        }

        public int ItemType
        {
            get
            {
                return dRMoneyEntity.ItemType;
            }
        }

        public CurrencyType ItemEnumType
        {
            get
            {
                return (CurrencyType)dRMoneyEntity.ItemType;
            }
        }

        public string Icon
        {
            get
            {
                return dRMoneyEntity.Icon;
            }
        }

        public string Name
        {
            get
            {
                return LanguageManager.GetLocalizedString(dRMoneyEntity.Name);
            }
        }

        public long InitNum
        {
            get
            {
                return dRMoneyEntity.InitNum;
            }
        }


        public MoneyEntityData(DRMoneyEntity drMoneyEntity)
        {
            this.dRMoneyEntity = drMoneyEntity;
        }
    }

    public sealed class MoneyOutputData
    {
        public DRMoneyOutput dRMoneyOutput;

        public int Id
        {
            get
            {
                return dRMoneyOutput.Id;
            }
        }

        public int MoneyEntityId
        {
            get
            {
                return dRMoneyOutput.MoneyEntityId;
            }
        }

        public int MoneyNum
        {
            get
            {
                return Random.Range(dRMoneyOutput.RangeNum[0], dRMoneyOutput.RangeNum[1]);
            }
        }

        public MoneyOutputData(DRMoneyOutput drMoneyOutput)
        {
            this.dRMoneyOutput = drMoneyOutput;
        }
    }

    public sealed class OfflineEarningsData
    {
        private DROfflineEarnings drOfflineEarnings;

        public int LevelId
        {
            get
            {
                return drOfflineEarnings.Id;
            }
        }

        public float EarningsNum
        {
            get
            {
                return drOfflineEarnings.Earning;
            }
        }

        public int UpperLimit
        {
            get
            {
                return drOfflineEarnings.UpperLimit;
            }
        }

        public OfflineEarningsData(DROfflineEarnings drOfflineEarnings)
        {
            this.drOfflineEarnings = drOfflineEarnings;
        }
    }

    public sealed class MoneyEntity : DataBase
    {
        private IDataTable<DRMoneyEntity> dtMoneyEntity;
        private Dictionary<int, MoneyEntityData> dicMoneyEntityData;

        private IDataTable<DRMoneyOutput> dtMoneyOutput;
        private Dictionary<int, MoneyOutputData> dicMoneyOutputData;

        private IDataTable<DROfflineEarnings> dtOfflineEarnings;
        private List<OfflineEarningsData> offlineEarningsData;


        private Dictionary<CurrencyType, int> dicBasicCurrencyIdLookUp;

        protected override void OnInit()
        {

        }

        protected override void OnPreload()
        {
            LoadDataTable("MoneyEntity");
            LoadDataTable("MoneyOutput");
            LoadDataTable("OfflineEarnings");
        }

        protected override void OnLoad()
        {
            dtMoneyEntity = GameEntry.DataTable.GetDataTable<DRMoneyEntity>();
            if (dtMoneyEntity == null)
                throw new System.Exception("Can not get data table PoolParam");

            dtMoneyOutput = GameEntry.DataTable.GetDataTable<DRMoneyOutput>();
            if (dtMoneyOutput == null)
                throw new System.Exception("Can not get data table MoneyOutput");

            dtOfflineEarnings = GameEntry.DataTable.GetDataTable<DROfflineEarnings>();
            if (dtOfflineEarnings == null)
                throw new System.Exception("Can not get data table OfflineEarnings");

            dicMoneyEntityData = new Dictionary<int, MoneyEntityData>();
            dicMoneyOutputData = new Dictionary<int, MoneyOutputData>();
            dicBasicCurrencyIdLookUp = new Dictionary<CurrencyType, int>();
            offlineEarningsData = new List<OfflineEarningsData>();

            DRMoneyEntity[] dRMoneyEntitys = dtMoneyEntity.GetAllDataRows();
            foreach (var dRMoneyEntity in dRMoneyEntitys)
            {
                MoneyEntityData poolParamData = new(dRMoneyEntity);
                dicMoneyEntityData.Add(dRMoneyEntity.Id, poolParamData);

                var currencyType = (CurrencyType)dRMoneyEntity.ItemType;
                if (currencyType == CurrencyType.Coin
                    || currencyType == CurrencyType.Gem)
                {
                    if (dicBasicCurrencyIdLookUp.ContainsKey(currencyType))
                    {
                        throw new System.Exception($"不允许有多种货币类型的定义 Type:{currencyType} ID:{dRMoneyEntity.Id}");
                    }
                    dicBasicCurrencyIdLookUp.Add(currencyType, dRMoneyEntity.Id);
                }
            }

            DRMoneyOutput[] dRMoneyOutputs = dtMoneyOutput.GetAllDataRows();
            foreach (var dRMoneyOutput in dRMoneyOutputs)
            {
                MoneyOutputData moneyOutputData = new(dRMoneyOutput);
                dicMoneyOutputData.Add(dRMoneyOutput.Id, moneyOutputData);
            }

            DROfflineEarnings[] drOfflineEarningss = dtOfflineEarnings.GetAllDataRows();
            foreach (var drOfflineEarnings in drOfflineEarningss)
            {
                OfflineEarningsData offlineEarningsData = new(drOfflineEarnings);
                this.offlineEarningsData.Add(offlineEarningsData);
            }
        }

        public bool GetCurrencyId(CurrencyType currencyType, out int itemId)
        {
            return dicBasicCurrencyIdLookUp.TryGetValue(currencyType, out itemId);
        }

        public bool CheckVaildMoneyId(int id)
        {
            return dicMoneyEntityData.ContainsKey(id);
        }

        public bool TryGetMoneyData(int id, out MoneyEntityData moenyData)
        {
            return dicMoneyEntityData.TryGetValue(id, out moenyData);
        }

        public MoneyEntityData GetMoneyEntityData(int id)
        {
            if (dicMoneyEntityData.ContainsKey(id))
            {
                return dicMoneyEntityData[id];
            }
            return null;
        }

        public void GetOffineEarningsData(int level, out float earnings, out int upperLimit)
        {
            earnings = 0;
            upperLimit = 0;
            for(int i = 0; i < offlineEarningsData.Count; i++)
            {
                if(offlineEarningsData[i].LevelId <= level)
                {
                    earnings = offlineEarningsData[i].EarningsNum;
                    upperLimit = offlineEarningsData[i].UpperLimit;
                    return;
                }
            }
            earnings = offlineEarningsData[^1].EarningsNum;
            upperLimit = offlineEarningsData[^1].UpperLimit;
        }

        public MoneyEntityData[] GetAllMoneyEntityData()
        {
            int index = 0;
            MoneyEntityData[] results = new MoneyEntityData[dicMoneyEntityData.Count];
            foreach (var poolParamData in dicMoneyEntityData.Values)
            {
                results[index++] = poolParamData;
            }
            return results;
        }

        public MoneyOutputData GetMoneyOutputData(int id)
        {
            if (dicMoneyOutputData.ContainsKey(id))
            {
                return dicMoneyOutputData[id];
            }
            return null;
        }

        protected override void OnUnload()
        {
            GameEntry.DataTable.DestroyDataTable<DRMoneyEntity>();
            dtMoneyEntity = null;
            dicMoneyEntityData = null;
        }


        protected override void OnShutdown()
        {
        }

    }
}
